home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / lib / mntlib44.zoo / mntlib / doprnt.c < prev    next >
C/C++ Source or Header  |  1993-10-12  |  28KB  |  1,226 lines

  1. /*
  2.  * Copyright (c) 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. /*
  19.  * minorly customized for gcc lib
  20.  *    ++jrb
  21.  * and for the sfp004 as well as the TT's 68881
  22.  *      mjr++
  23.  * and for turbo C and the MiNT library
  24.  *     ++um,mh
  25.  * and special M68881 and sfp004 version of cvt() added that uses fmovep for
  26.  * maximum precision, no bits lost anymore!
  27.  *    ++schwab
  28.  */
  29.  
  30. #ifndef __NO_FLOAT__
  31. #if 0
  32. static unsigned long
  33.     __notanumber[2] = { 0x7fffffffL, 0xffffffffL }; /* ieee NAN */
  34. #define NAN  (*((double *)&__notanumber[0]))
  35. static unsigned long
  36.     __p_infinity[2] = { 0x7ff00000L, 0x00000000L }; /* ieee NAN */
  37. #define INF  (*((double *)&__p_infinity[0]))
  38. #endif
  39.  
  40. #define NAN_HI 0x7fffffffL
  41. #define NAN_LO 0xffffffffL
  42. #define INF_HI 0x7ff00000L
  43. #define INF_LO 0x00000000L
  44.  
  45. #endif /* __NO_FLOAT__ */
  46.  
  47. #ifdef LIBC_SCCS
  48. static char sccsid[] = "@(#)doprnt.c    5.37 (Berkeley) 3/26/89";
  49. #endif /* LIBC_SCCS */
  50.  
  51. #include <compiler.h>
  52. #ifdef __TURBOC__
  53. #include <sys\types.h>
  54. #else
  55. #include <sys/types.h>
  56. #endif
  57. #include <stdarg.h>
  58. #include <stdio.h>
  59. #include <ctype.h>
  60. #include <string.h>
  61. #include <limits.h>
  62. #include <math.h>    /* mjr++ */
  63. #include "lib.h"
  64.  
  65. #ifndef __GNUC__    /* gcc lib has these typedefs in sys/types.h */
  66. #ifndef __MINT__    /* as does the MiNT library */
  67. typedef unsigned char u_char;
  68. typedef unsigned long u_long;
  69. #endif
  70. #endif
  71.  
  72. /* 11-bit exponent (VAX G floating point) is 308 decimal digits */
  73. #define    MAXEXP        308
  74.  
  75. /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
  76. # define    MAXFRACT    39
  77. # define    MAXEXP        308
  78.  
  79. #if defined (__M68881__) && !defined (sfp004)
  80. #  include <math-68881.h>    /* mjr: use the inline functions    */
  81. #endif    /* __M68881__ */
  82.  
  83. #define    DEFPREC        6
  84.  
  85. #define    BUF        (MAXEXP+MAXFRACT+1)    /* + decimal point */
  86.  
  87. #define    PUTC(ch)     if( (*putfunc)(ch, fp) == EOF ) return EOF;
  88.  
  89. #ifdef PRINTF_LONGLONG
  90. #define ARG(signtag) (\
  91.     (flags&LONGLONG ? \
  92.     (_ulonglong = (unsigned long long)va_arg(argp, signtag long long)) : 0 ) ,\
  93.     _ulong = \
  94.         flags&LONGLONG ? \
  95.             _ulonglong != 0ll : \
  96.         flags&LONGINT ? \
  97.             (unsigned long long)va_arg(argp, signtag long) : \
  98.         (flags&SHORTINT ? \
  99.             (unsigned long long)(signtag short)va_arg(argp, signtag int) : \
  100.              (unsigned long long)va_arg(argp, signtag int)) )
  101.      /* shorts are always promoted to ints; thus, it's `va_arg(... int)'
  102.       * for `flags&SHORTINT'!
  103.       */
  104. #else
  105. #define ARG(signtag) \
  106.     _ulong = \
  107.         flags&LONGINT ? \
  108.             (unsigned long)va_arg(argp, signtag long) : \
  109.         (flags&SHORTINT ? \
  110.             (unsigned long)(signtag short)va_arg(argp, signtag int) : \
  111.              (unsigned long)va_arg(argp, signtag int))
  112.      /* shorts are always promoted to ints; thus, it's `va_arg(... int)'
  113.       * for `flags&SHORTINT'!
  114.       */
  115. #endif
  116.  
  117. #define TEN_MUL(X)    ((((X) << 2) + (X)) << 1)
  118.  
  119. #define    todigit(c)    ((c) - '0')
  120. #define    tochar(n)    ((n) + '0')
  121.  
  122. #define    LONGINT        0x01        /* long integer */
  123. #define    LONGLONG    0x02        /* long long integer (8 bytes) */
  124. #define    LONGDBL        0x04        /* long double; unimplemented */
  125. #define    SHORTINT    0x08        /* short integer */
  126. #define    ALT        0x10        /* alternate form */
  127. #define    LADJUST        0x20        /* left adjustment */
  128. #define    ZEROPAD        0x40        /* zero (as opposed to blank) pad */
  129. #define    HEXPREFIX    0x80        /* add 0x or 0X prefix */
  130.  
  131. #ifndef __NO_FLOAT__
  132. #define __FLOATS__ 1
  133. #endif
  134.  
  135. #ifdef __FLOATS__
  136. # include    "flonum.h"
  137. #if defined (__M68881__) || defined (sfp004)
  138. static char *exponent __PROTO ((char *, int, int));
  139. static int _round __PROTO ((int, char *, char *, char *));
  140. static int cvt __PROTO ((double, int, int, char *, int, char *));
  141. #else
  142. #  if __STDC__
  143. static char *exponent(char *, int, int);
  144. static char *_round(double, int *, char *, char *, int, char *);
  145. static int  cvt(double, int, int, char *, int, char *, char *);
  146. #  else
  147. static char *exponent();
  148. static char *_round();
  149. static int  cvt();
  150. #  endif
  151. #endif /* __M68881__ */
  152. #endif
  153.  
  154. #if defined(__GNUC__) && (!defined(__NO_INLINE__))
  155. #ifdef __M68020__
  156.  
  157. #define _ICONV(NUMBER, BASE, BUF)                \
  158. {                                \
  159.   long i;                            \
  160.   do                                \
  161.     {                                \
  162.       __asm__ volatile                        \
  163.     ("divull %3,%1:%0"                    \
  164.      : "=d"((long)(NUMBER)), "=d"(i)            \
  165.      : "0"((long)(NUMBER)), "d"((long)(BASE)));        \
  166.       *--(BUF) = digs[i];                    \
  167.     }                                \
  168.   while (NUMBER);                        \
  169. }
  170.  
  171. #else /* !__M68020 */  
  172.  
  173. #define _ICONV(NUMBER, BASE, BUF)                 \
  174. {                                \
  175.                                 \
  176.     while((NUMBER) > 65535L)                    \
  177.     {                                \
  178.         extern unsigned long __udivsi3(); /* quot = d0, rem = d1 */ \
  179.         register long i __asm ("d1");                    \
  180.     __asm__ volatile("
  181.         movl    %3,sp@-;
  182.          movl    %2,sp@-;
  183.          jsr    ___udivsi3;
  184.          addqw    #8,sp;
  185.          movl    d0,%0"                    \
  186.              : "=r"((long)NUMBER), "=d"(i)            \
  187.          : "0"((long)NUMBER), "r"((long)BASE)        \
  188.              : "d0", "d1", "a0", "a1");            \
  189.         *--BUF = digs[i];                    \
  190.     }                                \
  191.     do                                 \
  192.     {                                \
  193.             short i;                        \
  194.         __asm__ volatile("
  195.          divu    %3,%2;
  196.          swap    %0;
  197.          movw    %0,%1;
  198.          clrw    %0;
  199.                 swap    %0"                    \
  200.              : "=d"((long)NUMBER), "=g"(i)            \
  201.          : "0"((long)NUMBER), "dm"((short)BASE));    \
  202.         *--BUF = digs[i];                    \
  203.     } while(NUMBER);                        \
  204. }
  205.  
  206. #endif /* __M68020 */
  207.  
  208. #else /* !__GNUC__ */
  209.  
  210. #define _ICONV(NUMBER, BASE, BUF)                 \
  211.   do {                                \
  212.     *--(BUF) = digs[(NUMBER) % (BASE)];                \
  213.     (NUMBER) /= (BASE);                        \
  214.   } while (NUMBER);
  215.  
  216. #endif /* __GNUC__ */
  217.  
  218. #ifdef PRINTF_LONGLONG
  219. #define _ICONVLL(NUMBER, BASE, BUF)                 \
  220.   do {                                \
  221.     *--(BUF) = digs[(NUMBER) % (BASE)];                \
  222.     (NUMBER) /= (BASE);                        \
  223.   } while (NUMBER);
  224. #endif
  225.  
  226. int _doprnt(putfunc, fp, fmt0, argp)
  227.     int (*putfunc) __PROTO ((int, FILE *));
  228.     FILE *fp;
  229.     const char *fmt0;
  230.     va_list argp;
  231. {
  232.     register const u_char *fmt;    /* format string */
  233.     register int ch;    /* character from fmt */
  234.     register int cnt;    /* return value accumulator */
  235.     register int n;        /* random handy integer */
  236.     register char *t;    /* buffer pointer */
  237. #ifdef    __FLOATS__
  238. /*    double _double;        *//* double precision arguments %[eEfgG] */
  239.     union double_di _dd;    /* _double is #defined to be _dd later on */
  240.     char softsign;        /* temporary negative sign for floats */
  241. #endif    /* __FLOATS__ */
  242. #ifdef PRINTF_LONGLONG
  243.     typedef unsigned long long _ulonglongtype;
  244.     typedef long long _ulonglongsignedtype;
  245.     _ulonglongtype _ulonglong;
  246. #endif
  247.     typedef u_long _ulongtype;
  248.     typedef long _ulongsignedtype;
  249.     _ulongtype _ulong;        /* integer arguments %[diouxX] */
  250.     short base;        /* base for [diouxX] conversion */
  251.     short dprec;        /* decimal precision in [diouxX] */
  252.     short fieldsz;        /* field size expanded by sign, etc */
  253.     short flags;        /* flags as above */
  254.     short fpprec;        /* `extra' floating precision in [eEfgG] */
  255.     short prec;        /* precision from format (%.3d), or -1 */
  256.     short realsz;        /* field size expanded by decimal precision */
  257.     short size;        /* size of converted field or string */
  258.     short width;        /* width from format (%8d), or 0 */
  259.     char sign;        /* sign prefix (' ', '+', '-', or \0) */
  260.     char *digs;        /* digits for [diouxX] conversion */
  261.     char buf[BUF];        /* space for %c, %[diouxX], %[eEfgG] */
  262.  
  263.     fmt = (const u_char *) fmt0;
  264.     digs = "0123456789abcdef";
  265.     for (cnt = 0;; ++fmt) {
  266.         if ((ch = *fmt) == 0)
  267.             return (cnt);
  268.         if (ch != '%') {
  269.             PUTC(ch);
  270.             cnt++;
  271.             continue;
  272.         }
  273.         flags = 0; dprec = 0; fpprec = 0; width = 0;
  274.         prec = -1;
  275.         sign = '\0';
  276.  
  277. rflag:        switch (*++fmt) {
  278.         case ' ':
  279.             /*
  280.              * ``If the space and + flags both appear, the space
  281.              * flag will be ignored.''
  282.              *    -- ANSI X3J11
  283.              */
  284.             if (!sign)
  285.                 sign = ' ';
  286.             goto rflag;
  287.         case '#':
  288.             flags |= ALT;
  289.             goto rf